#include <stdio.h>
#include "dbcParse_PublicDefine.h"


/* 设置字节中的指定位，同时不改变其他位的值 */
static uint8 set_bits(uint8 byte, uint32 start_bit, uint32 num_bits, uint8 value)
{
    uint8 clear_mask = ~(((1 << num_bits) - 1) << start_bit);   /* 创建一个掩码，用于清除要设置的位 */
    uint8 set_mask = ((1 << num_bits) - 1) << start_bit;    /* 创建一个掩码，用于设置新值 */
    uint8 new_bits = (value & ((1 << num_bits) - 1)) << start_bit;  /* 将value左移以匹配start_bit的位置，并与set_mask进行按位与操作 */

    /* 清除旧的位，并设置新的位 */
    return (byte & clear_mask) | (new_bits & set_mask);
}

/* 获取从第0位开始的指定长度数据 */
static uint8 extract_bits(uint64 value, uint8 length)
{
    uint64 mask = ((1ULL << length) - 1); /* 创建掩码 */
    return (uint8)(value & mask); /* 应用掩码并右移以对齐位 */
}


static inline uint8 sigPhyvalIsUinttypeTransfer
(
    const tCANSIGNALCONFIG *canSigConfig,
    uint64 canSigPhyValUint64,
    uint64 *pCanSigRawValUint64,
    sint64 *pCanSigRawValSint64
)
{
    if(SIGRAWDATATYPE_UNSIGNED == canSigConfig->rawDataType)
    {
        *pCanSigRawValUint64 = (canSigPhyValUint64 - (uint64)canSigConfig->offsetVal)/(uint64)canSigConfig->factorVal;  /* 计算结果应该为正值，否则错误 */
    }
    else if(SIGRAWDATATYPE_SIGNED == canSigConfig->rawDataType)
    {
        *pCanSigRawValSint64 = (sint64)((canSigPhyValUint64 - (uint64)canSigConfig->offsetVal)/(uint64)canSigConfig->factorVal);
    }
    // if((SIGFACTOROFFSETDATATYPE_INTPOSITIVE == canSigConfig->factorDataType) && (SIGFACTOROFFSETDATATYPE_INTPOSITIVE == canSigConfig->offsetDataType))
    // {
    //     if(SIGRAWDATATYPE_UNSIGNED == canSigConfig->rawDataType)
    //     {
    //         *pCanSigRawValUint64 = (canSigPhyValUint64 - (uint64)canSigConfig->offsetVal)/(uint64)canSigConfig->factorVal;  /* 计算结果应该为正值，否则错误 */
    //     }
    //     else if(SIGRAWDATATYPE_SIGNED == canSigConfig->rawDataType)
    //     {
    //         *pCanSigRawValSint64 = (sint64)((canSigPhyValUint64 - (uint64)canSigConfig->offsetVal)/(uint64)canSigConfig->factorVal);
    //     }
    // }
    // else
    // {
    //     return RET_DATATYPE_ERR;
    // }

    return RET_OK;
}

// canSigConfig: 信号的配置参数
// pCanRawData: CAN报文原始数据，需要将打包后的信号值存放到CAN报文的合适位置
// pData: 信号物理值指针
uint8 dbcParse_CanSignalEncode(const tCANSIGNALCONFIG *canSigConfig, uint8 *pCanRawData, void *pData)
{
#ifdef PARAMETER_CHECK
	/* 参数检查，不合理的参数直接返回ERR */
	if(	(((SIGFACTOROFFSETDATATYPE_FLOAT==canSigConfig->factorDataType)||(SIGFACTOROFFSETDATATYPE_FLOAT==canSigConfig->offsetDataType)) && (SIGPHYDATATYPE_FLOAT==canSigConfig->dataType))
		||((SIGFACTOROFFSETDATATYPE_INTPOSITIVE==canSigConfig->factorDataType) && (SIGFACTOROFFSETDATATYPE_INTPOSITIVE==canSigConfig->offsetDataType) && (SIGRAWDATATYPE_UNSIGNED==canSigConfig->rawDataType) && (canSigConfig->dataType>=SIGPHYDATATYPE_UINT8 && canSigConfig->dataType<=SIGPHYDATATYPE_UINT64))
		||((SIGFACTOROFFSETDATATYPE_INTNEGATIVE==canSigConfig->factorDataType || SIGFACTOROFFSETDATATYPE_INTNEGATIVE==canSigConfig->offsetDataType) && (SIGRAWDATATYPE_UNSIGNED==canSigConfig->rawDataType) && (canSigConfig->dataType>=SIGPHYDATATYPE_SINT8 && canSigConfig->dataType<=SIGPHYDATATYPE_SINT64))
		||((SIGFACTOROFFSETDATATYPE_FLOAT!=canSigConfig->factorDataType && SIGFACTOROFFSETDATATYPE_FLOAT!=canSigConfig->offsetDataType) && (SIGRAWDATATYPE_SIGNED==canSigConfig->rawDataType) && (canSigConfig->dataType>=SIGPHYDATATYPE_SINT8 && canSigConfig->dataType<=SIGPHYDATATYPE_SINT64))
	)
	{
		// continue
	}
	else
	{
		return RET_DATATYPE_ERR;
	}
#endif

    uint64 canSigPhyValUint64 = 0u;
    sint64 canSigPhyValSint64 = 0;
    double canSigPhyValFloat = 0.0;

    uint64 canSigFactorUint64 = 0u;
    sint64 canSigFactorSint64 = 0;


    uint64 canSigOffsetUint64 = 0u;
    sint64 canSigOffsetSint64 = 0u;

    uint64 canSigRawValUint64 = 0u;
    sint64 canSigRawValSint64 = 0;

    

    /* 根据信号物理值，计算出信号的CAN报文值 */
    switch(canSigConfig->dataType)
    {
        // case SIGPHYDATATYPE_UINT8:
        //     canSigPhyValUint64= *((uint8 *)pData);
        //     if( (canSigConfig->minimumValid && (canSigPhyValUint64<canSigConfig->minimum))
        //         || ((canSigConfig->maxminumValid) && (canSigPhyValUint64>canSigConfig->maximum))  )
        //     {
        //         return RET_SIGPHYVAL_EXCEED_MAXMIN;
        //     }
        //     if(RET_OK != sigPhyvalIsUinttypeTransfer(canSigConfig, canSigPhyValUint64, &canSigRawValUint64, &canSigRawValSint64))
        //     {
        //         return RET_DATATYPE_ERR;
        //     }
        // break;

        // case SIGPHYDATATYPE_UINT16:
        //     canSigPhyValUint64= *((uint16 *)pData);
        //     if((canSigPhyValUint64<=canSigConfig->minimum) || (canSigPhyValUint64>=canSigConfig->maximum))
        //     {
        //         return RET_SIGPHYVAL_EXCEED_MAXMIN;
        //     }
        //     if(RET_OK != sigPhyvalIsUinttypeTransfer(canSigConfig, canSigPhyValUint64, &canSigRawValUint64, &canSigRawValSint64))
        //     {
        //         return RET_DATATYPE_ERR;
        //     }
        // break;

        // case SIGPHYDATATYPE_UINT32:
        //     canSigPhyValUint64= *((uint32 *)pData);
        //     if((canSigPhyValUint64<=canSigConfig->minimum) || (canSigPhyValUint64>=canSigConfig->maximum))
        //     {
        //         return RET_SIGPHYVAL_EXCEED_MAXMIN;
        //     }
        //     if(RET_OK != sigPhyvalIsUinttypeTransfer(canSigConfig, canSigPhyValUint64, &canSigRawValUint64, &canSigRawValSint64))
        //     {
        //         return RET_DATATYPE_ERR;
        //     }
        // break;
        
        // case SIGPHYDATATYPE_UINT64:
        //     canSigPhyValUint64= *((uint64 *)pData);
        //     if((canSigPhyValUint64<=canSigConfig->minimum) || (canSigPhyValUint64>=canSigConfig->maximum))
        //     {
        //         return RET_SIGPHYVAL_EXCEED_MAXMIN;
        //     }
        //     if(RET_OK != sigPhyvalIsUinttypeTransfer(canSigConfig, canSigPhyValUint64, &canSigRawValUint64, &canSigRawValSint64))
        //     {
        //         return RET_DATATYPE_ERR;
        //     }
        // break;


        case SIGPHYDATATYPE_UINT8:
        case SIGPHYDATATYPE_UINT16:
        case SIGPHYDATATYPE_UINT32:
        case SIGPHYDATATYPE_UINT64:
            /* 根据信号数据类型进行数据类型转换 */
            if(SIGPHYDATATYPE_UINT8 == canSigConfig->dataType)
            {
                canSigPhyValUint64= *((uint8 *)pData);
            }
            else if(SIGPHYDATATYPE_UINT16 == canSigConfig->dataType)
            {
                canSigPhyValUint64= *((uint16 *)pData);
            }
            else if(SIGPHYDATATYPE_UINT32 == canSigConfig->dataType)
            {
                canSigPhyValUint64= *((uint32 *)pData);
            }
            else if(SIGPHYDATATYPE_UINT64 == canSigConfig->dataType)
            {
                canSigPhyValUint64= *((uint64 *)pData);
            }

#ifdef CANSIGNAL_PHYVAL_MAXMIN_CHECK            
            /* 判断信号物理值是否超过限值 */
            if( (canSigConfig->minimumValid && (canSigPhyValUint64<canSigConfig->minimum))
                || ((canSigConfig->maxminumValid) && (canSigPhyValUint64>canSigConfig->maximum))  )
            {
                return RET_SIGPHYVAL_EXCEED_MAXMIN;
            }
#endif            

            /* 根据信号物理值计算CAN报文原始值 */
            if(RET_OK != sigPhyvalIsUinttypeTransfer(canSigConfig, canSigPhyValUint64, &canSigRawValUint64, &canSigRawValSint64))
            {
                return RET_DATATYPE_ERR;
            }

            break;

        case SIGPHYDATATYPE_SINT8:
        case SIGPHYDATATYPE_SINT16:
        case SIGPHYDATATYPE_SINT32:
        case SIGPHYDATATYPE_SINT64:
            /* 根据信号数据类型进行数据类型转换 */
            if(SIGPHYDATATYPE_SINT8 == canSigConfig->dataType)
            {
                canSigPhyValSint64= *((sint8 *)pData);
            }
            else if(SIGPHYDATATYPE_SINT16 == canSigConfig->dataType)
            {
                canSigPhyValSint64= *((sint16 *)pData);
            }
            else if(SIGPHYDATATYPE_SINT32 == canSigConfig->dataType)
            {
                canSigPhyValSint64= *((sint32 *)pData);
            }
            else if(SIGPHYDATATYPE_SINT64 == canSigConfig->dataType)
            {
                canSigPhyValSint64= *((sint64 *)pData);
            }

#ifdef CANSIGNAL_PHYVAL_MAXMIN_CHECK
            /* 判断信号物理值是否超过限值 */
            if( (canSigConfig->minimumValid && (canSigPhyValSint64<canSigConfig->minimum))
                || ((canSigConfig->maxminumValid) && (canSigPhyValSint64>canSigConfig->maximum))  )
            {
                return RET_SIGPHYVAL_EXCEED_MAXMIN;
            }
#endif            

            /* 根据信号物理值计算CAN报文原始值 */
            canSigFactorSint64 = (sint64)canSigConfig->factorVal;
            canSigOffsetSint64 = (sint64)canSigConfig->offsetVal;
            if(SIGRAWDATATYPE_UNSIGNED == canSigConfig->rawDataType)
            {
                canSigRawValUint64 = (uint64)((canSigPhyValSint64 - canSigOffsetSint64)/canSigFactorSint64);    /* 计算结果应该为正值，否则错误 */
            }
            else if(SIGRAWDATATYPE_SIGNED == canSigConfig->rawDataType)
            {
                canSigRawValSint64 = (sint64)((canSigPhyValSint64 - canSigOffsetSint64)/canSigFactorSint64);
            }
            // if((SIGFACTOROFFSETDATATYPE_INTNEGATIVE == canSigConfig->factorDataType) || (SIGFACTOROFFSETDATATYPE_INTNEGATIVE == canSigConfig->offsetDataType))
            // {
            //     canSigFactorSint64 = (sint64)canSigConfig->factorVal;
            //     canSigOffsetSint64 = (sint64)canSigConfig->offsetVal;
            //     if(SIGRAWDATATYPE_UNSIGNED == canSigConfig->rawDataType)
            //     {
            //         canSigRawValUint64 = (uint64)((canSigPhyValSint64 - canSigOffsetSint64)/canSigFactorSint64);    /* 计算结果应该为正值，否则错误 */
            //     }
            //     else if(SIGRAWDATATYPE_SIGNED == canSigConfig->rawDataType)
            //     {
            //         canSigRawValSint64 = (sint64)((canSigPhyValSint64 - canSigOffsetSint64)/canSigFactorSint64);
            //     }
            // }
            // else
            // {
            //     return RET_DATATYPE_ERR;
            // }
        break;

        case SIGPHYDATATYPE_FLOAT:
            /* 根据信号数据类型进行数据类型转换 */
            canSigPhyValFloat= *((double *)pData);

#ifdef CANSIGNAL_PHYVAL_MAXMIN_CHECK
            /* 判断信号物理值是否超过限值 */
            if( (canSigConfig->minimumValid && (canSigPhyValFloat<canSigConfig->minimum))
                || ((canSigConfig->maxminumValid) && (canSigPhyValFloat>canSigConfig->maximum))  )
            {
                return RET_SIGPHYVAL_EXCEED_MAXMIN;
            }
#endif
            
            /* 根据信号物理值计算CAN报文原始值 */
            if(SIGRAWDATATYPE_UNSIGNED == canSigConfig->rawDataType)
            {
                canSigRawValUint64 = (uint64)((canSigPhyValFloat - canSigConfig->offsetVal)/canSigConfig->factorVal);     /* 计算结果应该为正值，否则错误 */
            }
            else if(SIGRAWDATATYPE_SIGNED == canSigConfig->rawDataType)
            {
                canSigRawValSint64 = (sint64)((canSigPhyValFloat - canSigConfig->offsetVal)/canSigConfig->factorVal);
            }
        break;
    }

    /* 根据信号的配置，将信号的CAN报文值填入CAN报文的合适位置 */
    if(SIGBYTEENDIAN_MOTOROLAR == canSigConfig->dataEndian)
    {
        /* 摩托罗拉格式 */
        if((canSigConfig->startBit+1 - canSigConfig->lengthBits)/8 == (canSigConfig->startBit/8))
        {
            /* 信号在同一个字节中 */
            uint8 byteIndex = canSigConfig->startBit/8;
            uint8 startSetBit = (canSigConfig->startBit-canSigConfig->lengthBits+1)%8;
            if(SIGRAWDATATYPE_UNSIGNED == canSigConfig->rawDataType)
            {
                pCanRawData[byteIndex] = set_bits(pCanRawData[byteIndex], startSetBit, canSigConfig->lengthBits, canSigRawValUint64);
            }
            else if(SIGRAWDATATYPE_SIGNED == canSigConfig->rawDataType)
            {
                pCanRawData[byteIndex] = set_bits(pCanRawData[byteIndex], startSetBit, canSigConfig->lengthBits, canSigRawValSint64);
            }
        }
        else
        {
            /* 信号超过了一个字节 */
            uint8 startByteIndex = canSigConfig->startBit/8;		/* 起始位所在字节序号 */
            uint8 startByteBits = canSigConfig->startBit - startByteIndex*8 + 1;		/* 起始位所在字节中，信号所占据的bit位数 */
            uint8 sigLeftBitsExceptFristByte = canSigConfig->lengthBits - startByteBits;		/* 信号除去起始位所在字节所占位数的剩余位数 */
            uint8 endByteIndex = sigLeftBitsExceptFristByte/8 + 1 + startByteIndex;		/* 信号结束位所在字节序号 */
            uint8 endByteBits = sigLeftBitsExceptFristByte - (sigLeftBitsExceptFristByte/8)*8;	/* 信号在结束位所在字节中，所占据的bit位数 */

            if(SIGRAWDATATYPE_UNSIGNED == canSigConfig->rawDataType)
            {
                /* 设置信号所在的最后一个字节中相应bit位置 */
                uint8 lastByteStartBit = ((endByteIndex+1)*8 - 1 - endByteBits + 1)%8;  /* 信号在最后一个字节中的设置起始位 */
                uint8 lastByteData = extract_bits(canSigRawValUint64, endByteBits);
                pCanRawData[endByteIndex] = set_bits(pCanRawData[endByteIndex], lastByteStartBit, endByteBits, lastByteData);   /* 设置最后一个字节 */
                canSigRawValUint64 = canSigRawValUint64>>endByteBits;
                
                /* 设置信号在中间字节的Byte值 */
                uint8 i=0u;
                for(i=0; i<endByteIndex-startByteIndex-1; i++)
                {
                    pCanRawData[endByteIndex-i-1]= canSigRawValUint64&0x00FF;
                    canSigRawValUint64 = canSigRawValUint64>>8;
                }

                /* 设置信号所在的第一个字节中相应bit位置 */
                pCanRawData[startByteIndex] = set_bits(pCanRawData[startByteIndex], 0u, startByteBits, (uint8)canSigRawValUint64);
            }
            else if(SIGRAWDATATYPE_SIGNED == canSigConfig->rawDataType)
            {
                /* 设置信号所在的最后一个字节中相应bit位置 */
                uint8 lastByteStartBit = ((endByteIndex+1)*8 - 1 - endByteBits + 1)%8;  /* 信号在最后一个字节中的设置起始位 */
                uint8 lastByteData = extract_bits(canSigRawValSint64, endByteBits);
                pCanRawData[endByteIndex] = set_bits(pCanRawData[endByteIndex], lastByteStartBit, endByteBits, lastByteData);   /* 设置最后一个字节 */
                canSigRawValSint64 = canSigRawValSint64>>endByteBits;
                
                /* 设置信号在中间字节的Byte值 */
                uint8 i=0u;
                for(i=0; i<endByteIndex-startByteIndex-1; i++)
                {
                    pCanRawData[endByteIndex-i-1]= canSigRawValSint64&0x00FF;
                    canSigRawValSint64 = canSigRawValSint64>>8;
                }

                /* 设置信号所在的第一个字节中相应bit位置 */
                pCanRawData[startByteIndex] = set_bits(pCanRawData[startByteIndex], 0u, startByteBits, (uint8)canSigRawValSint64);
            }
        }
    }
    else if(SIGBYTEENDIAN_INTEL == canSigConfig->dataEndian)
    {
        /* 因特尔格式数据解析 */
        if((canSigConfig->startBit+canSigConfig->lengthBits-1)/8 == (canSigConfig->startBit/8))
        {
            /* 信号在同一个字节中 */
            uint8 byteIndex = canSigConfig->startBit/8;
            uint8 startSetBit = canSigConfig->startBit - (canSigConfig->startBit/8)*8;
            if(SIGRAWDATATYPE_UNSIGNED == canSigConfig->rawDataType)
            {
                pCanRawData[byteIndex] = set_bits(pCanRawData[byteIndex], startSetBit, canSigConfig->lengthBits, canSigRawValUint64);
            }
            else if(SIGRAWDATATYPE_SIGNED == canSigConfig->rawDataType)
            {
                pCanRawData[byteIndex] = set_bits(pCanRawData[byteIndex], startSetBit, canSigConfig->lengthBits, canSigRawValSint64);
            }
        }
        else
        {
            /* 信号超过了一个字节 */
            // 起始位指向 lsb
            uint8 startByteIndex = canSigConfig->startBit/8;		/* 起始位所在字节序号 */
            // uint8 startByteBits = canSigConfig->startBit - startByteIndex*8 + 1;		/* 起始位所在字节中，信号所占据的bit位数 */
            uint8 startByteBits = (canSigConfig->startBit/8+1)*8 - canSigConfig->startBit;// - startByteIndex*8 + 1;		/* 起始位所在字节中，信号所占据的bit位数 */
            uint8 sigLeftBitsExceptFristByte = canSigConfig->lengthBits - startByteBits;		/* 信号除去起始位所在字节所占位数的剩余位数 */
            uint8 endByteIndex = sigLeftBitsExceptFristByte/8 + 1 + startByteIndex;		/* 信号结束位所在字节序号 */
            uint8 endByteBits = sigLeftBitsExceptFristByte - (sigLeftBitsExceptFristByte/8)*8;	/* 信号在结束位所在字节中，所占据的bit位数 */
            
            if(SIGRAWDATATYPE_UNSIGNED == canSigConfig->rawDataType)
            {
                /* 设置信号所在的最后一个字节中相应bit位置 */
                uint8 startByteStartBit = 8u - startByteBits;
                uint8 startByteData = extract_bits(canSigRawValUint64, startByteBits);
                pCanRawData[startByteIndex] = set_bits(pCanRawData[startByteIndex], startByteStartBit, startByteBits, startByteData);   /* 设置最后一个字节 */
                canSigRawValUint64 = canSigRawValUint64>>startByteBits;

                /* 设置信号在中间字节的Byte值 */
                uint8 i=0u;
                for(i=0; i<endByteIndex-startByteIndex-1; i++)
                {
                    pCanRawData[endByteIndex-i-1]= canSigRawValUint64&0x00FF;
                    canSigRawValUint64 = canSigRawValUint64>>8;
                }
                
                /* 设置信号所在的第一个字节中相应bit位置 */
                pCanRawData[endByteIndex] = set_bits(pCanRawData[endByteIndex], 0u, endByteBits, (uint8)canSigRawValUint64);
               
            }
            else if(SIGRAWDATATYPE_SIGNED == canSigConfig->rawDataType)
            {
                /* 设置信号所在的最后一个字节中相应bit位置 */
                uint8 startByteStartBit = 8u - startByteBits;
                uint8 startByteData = extract_bits(canSigRawValSint64, startByteBits);
                pCanRawData[startByteIndex] = set_bits(pCanRawData[startByteIndex], startByteStartBit, startByteBits, startByteData);   /* 设置最后一个字节 */
                canSigRawValSint64 = canSigRawValSint64>>startByteBits;

                /* 设置信号在中间字节的Byte值 */
                uint8 i=0u;
                for(i=0; i<endByteIndex-startByteIndex-1; i++)
                {
                    pCanRawData[endByteIndex-i-1]= canSigRawValSint64&0x00FF;
                    canSigRawValSint64 = canSigRawValSint64>>8;
                }
                
                /* 设置信号所在的第一个字节中相应bit位置 */
                pCanRawData[endByteIndex] = set_bits(pCanRawData[endByteIndex], 0u, endByteBits, (uint8)canSigRawValSint64);
            }
        }
    }

    return RET_OK;
}
